package com.fh.aspect;

import com.alibaba.fastjson.JSON;
import com.fh.annotation.SysLog;
import com.fh.mapper.OperatorLogMapper;
import com.fh.model.system.OperatorLog;
import com.fh.util.IPUtils;
import com.fh.util.JsonUtil;
import com.fh.util.ResultJSON;
import com.fh.util.UserUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

/**
 * 系统日志，切面处理类
 *
 * @author xuxiaorong
 */
@Aspect
@Component
public class SysLogAspect {
	Logger logger = LoggerFactory.getLogger(SysLogAspect.class);
	
	@Autowired
	private OperatorLogMapper logService;
	
	@Pointcut("@annotation(com.fh.annotation.SysLog)")
	public void logPointCut() {
		
	}
	
	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		long beginTime = System.currentTimeMillis();
		//获取签名
		MethodSignature signature = (MethodSignature) point.getSignature();
		Method method = signature.getMethod();
		//请求的方法名
		String className = point.getTarget().getClass().getName();
		String methodName = signature.getName();
		SysLog syslogAnnotation = method.getAnnotation(SysLog.class);
		Object result = null;
		//操作记录  参数+数据
		StringBuilder info = new StringBuilder();
		Integer status = new Integer(0);
		//设置IP地址  操作人+Ip
		String ip = "";
		String parm = getParam(JSON.toJSONString(((ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes()).getRequest().getParameterMap()), syslogAnnotation.value());
		try {
			//系统注销时获取
			ip = before();
			//执行方法
			result = point.proceed();
			try {
				info.append("参数：")
						.append(parm)
						.append(";返回值：")
						.append(result == null ? "" : (String) JsonUtil.toJsonString(result));
				String falseStr = "false";
				if (result instanceof ResultJSON && JSON.toJSONString(result).contains(falseStr)) {
					status = 1;
				}
			} catch (Exception ex) {
				logger.error("[" + syslogAnnotation.value() + "]" + "转json异常", ex);
				info.setLength(0);
				info.append("参数：").append(parm).append("异常：转json异常");
				status = 1;
			}
			//系统登陆是获取
			ip = after(ip);
		} catch (Throwable ex) {//异常通知
			logger.error("[" + syslogAnnotation.value() + "]" + className + "." + methodName +
					"()：执行异常" + ex.getMessage(), ex);
			info.setLength(0);
			info.append("参数：").append(parm).append("异常：" + JSON.toJSONString(ex.getStackTrace()[0]));
			status = 1;
		}
		//执行时长(毫秒)
		long time = System.currentTimeMillis() - beginTime;
		logger.info("操作日志信息{" + className + "." + methodName
				+ "()：执行" + syslogAnnotation.value() + "耗时" + "" + time + "毫秒}");
		//保存日志
		saveSysLog(syslogAnnotation.value(), status, info, ip, result, time);
		//logger.info("result: " + result);
		return result;
	}
	
	/**
	 * 保存操作日志
	 *
	 * @param optType 操作类型
	 * @param status  操作结果  状态 0成功、1失败
	 * @param info    操作记录  参数+数据
	 * @param result  执行结果
	 * @param time    执行时间
	 */
	private void saveSysLog(String optType, int status, StringBuilder info, String ip, Object result, Long time) {
		try {
			OperatorLog sysLog = new OperatorLog();
			sysLog.setSysType((byte) 1);
			//操作类型
			sysLog.setOptType(optType);
			//设置IP地址  操作人+Ip
			try {
				sysLog.setOperatorName(ip.split(";")[0]);
				sysLog.setIp(ip.split(";")[1]);
			} catch (Exception e) {
				logger.error("登陆失败,账号或密码或验证码错误.");
				return;
			}
			//操作记录  参数+数据
            if(info!=null) {
                String str = info.toString();
                if (!StringUtils.isEmpty(str) && str.length() > 100) {
                    str = str.substring(0, 100);
                }
                sysLog.setOptInfo(str);
            }
			//操作结果  状态 0成功、1失败
			sysLog.setOptStatus(status);
			//创建时间
			sysLog.setCreateTime(new Date());
			//保存系统日志
			logService.insert(sysLog);
		} catch (Exception e) {
			logger.error("保存操作日志异常：" , e);
		}
	}
	
	private String getIp() {
		HttpServletRequest request = ((ServletRequestAttributes)
				RequestContextHolder.getRequestAttributes()).getRequest();
		String ip = UserUtils.getRealUser().getNAME() + ";IP：" + IPUtils.getIpAddr(request);
		return ip;
	}
	
	
	private String before() {
		return UserUtils.getRealUser() != null ? getIp() : "";
	}
	
	private String after(String ip) {
		return "".equals(ip) ? before() : ip;
	}
	
	
	private String getParam(String parm,String annotation){
		logger.info("parm:" + parm);
		StringBuilder sb = new StringBuilder();
		String msg = "系统登陆";
		if (msg.equals(annotation)) {
			try {
				sb.append(parm.split(",fh")[0]).append(parm.split(",fh")[2]);
			} catch (Exception e) {
				logger.error("getParam，数组越界");
			}
		} else {
			sb.append(parm);
		}
		return sb.toString();
	}
}
